#include "stdafx.h"
#include "Sheet.h"

namespace ExcelLibrary
{
	CSheet::CSheet(_Recordset* pRecordset) : m_dwRefCount(0), m_pRecordset(pRecordset), m_pFields(NULL), m_ulRowPos(0), m_ulRowCount(0), m_ulColumnCount(0)
	{
		AddRef();
	}

	CSheet::~CSheet()
	{
		m_pFields->Release();

		m_pRecordset->Release();
	}

	HRESULT STDMETHODCALLTYPE CSheet::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject)
	{
		m_dwRefCount++;
		*ppvObject = static_cast<void*>(this);
		return S_OK;
	}
    
	ULONG STDMETHODCALLTYPE CSheet::AddRef(void)
	{
		m_dwRefCount++;
		return m_dwRefCount;
	}
    
	ULONG STDMETHODCALLTYPE CSheet::Release(void)
	{
		m_dwRefCount--;

		DWORD dwRefCount = m_dwRefCount;

		if (dwRefCount == 0)
		{
			delete this;
		}

		return dwRefCount;
	}

	bool CSheet::Initialize()
	{
		if (FAILED(m_pRecordset->get_Fields(&m_pFields)))
		{
			return false;
		}

		ADO_LONGPTR RowCount = 0;
		if (FAILED(m_pRecordset->get_RecordCount(&RowCount)))
		{
			return false;
		}

		m_ulRowCount = RowCount;

		long lCount = 0;
		if (FAILED(m_pFields->get_Count(&lCount)))
		{
			return 0;
		}

		m_ulColumnCount = lCount;

		return true;
	}

	bool CSheet::EndOfRow()
	{
		if (m_ulRowPos == m_ulRowCount)
		{
			return true;
		}

		return false;
	}

	bool CSheet::MoveNextRow()
	{
		if (FAILED(m_pRecordset->MoveNext()))
		{
			return false;
		}

		++m_ulRowPos;

		return true;
	}
	
	bool CSheet::MovePrevRow()
	{
		if (m_ulRowPos == 1)
		{
			return false;
		}

		if (FAILED(m_pRecordset->MovePrevious()))
		{
			return false;
		}

		--m_ulRowPos;

		return true;
	}

	bool CSheet::MoveRow(unsigned long ulPos)
	{
		if (m_ulRowCount < (ulPos + 1))
		{
			return false;
		}

		bool bPrev = false;

		int nMoveCount = int((ulPos + 1) - m_ulRowPos);

		if (nMoveCount < 0)
		{
			bPrev = true;
			nMoveCount = abs(nMoveCount);
		}
		
		while (nMoveCount)
		{
			if (bPrev)
			{
				if (FAILED(m_pRecordset->MovePrevious()))
				{
					return false;
				}
			}
			else
			{
				if (FAILED(m_pRecordset->MoveNext()))
				{
					return false;
				}
			}
			--nMoveCount;
		}

		m_ulRowPos = ulPos;

		return true;
	}

	unsigned long CSheet::GetRowCount()
	{
		return m_ulRowCount;
	}

	unsigned long CSheet::GetColumnCount()
	{
		return m_ulColumnCount;
	}

	IColumn* CSheet::GetColumn(unsigned long ulColumnPos)
	{
		Field* pField = NULL;
		if (FAILED(m_pFields->get_Item(variant_t(static_cast<short>(ulColumnPos)), &pField)))
		{
			return NULL;
		}

		CColumn* pColumn = new CColumn(pField);

		if (!pColumn->Initialize())
		{
			delete pColumn;
			pColumn = NULL;
		}

		return pColumn;
	}
}